package com.thuan.android3d;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.opengl.GLUtils;

public class Sprite extends GameObject{
	
	private FloatBuffer verticesBuffer;
	private ShortBuffer indicesBuffer;
	private FloatBuffer textureCoordsBuffer;
	private int textureID;
	private int numOfIndices;
	private boolean loadedTexture;
	private boolean touched;
	
	public Sprite(Bitmap bitmap, float x, float y) {
		
		this.bitmap = bitmap;
		width = bitmap.getWidth();
		height = bitmap.getHeight();
		this.x = x;
		this.y = y;
		loadedTexture = false;
		touched = false;
		
		left = x - width/2;
		right = x + width/2;
		bottom = y - height/2;
		top = y + height/2;
		
		initBuffer();
	}
	
	private void initBuffer() {

		float[] vertices = {
				left,top,0f,
				right,top,0f,
				right,bottom,0f,
				left,bottom,0f
		};
		
		
		short[] indices = {
				0,3,1,
				3,2,1
		};
		
		float[] textureCoords = {
				0,0,
				1,0,
				1,1,
				0,1
		};
		
		setVerticesBuffer(vertices);
		setIndicesBuffer(indices);
		setTextureCoordsBuffer(textureCoords);
		
	}
	
	public void update() {
		left = x - width/2;
		right = x + width/2;
		bottom = y - height/2;
		top = y + height/2;
	}
	
	public void draw(GL10 gl) {
		
		if (!loadedTexture) {
			loadGLTexture(gl);
			loadedTexture = true;
		}
		
		gl.glEnable(GL10.GL_TEXTURE_2D);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
		
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, verticesBuffer);
		gl.glColor4f(1, 1, 1, 1);
		
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureCoordsBuffer);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);
		
		gl.glPushMatrix();
		gl.glTranslatef(tranX, tranY, 0);
		gl.glDrawElements(GL10.GL_TRIANGLES, numOfIndices, 
				GL10.GL_UNSIGNED_SHORT, indicesBuffer);
		
		gl.glPopMatrix();
		
		gl.glDisable(GL10.GL_TEXTURE_2D);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		
	}
	
	
	private void loadGLTexture(GL10 gl) { // New function
		// Generate one texture pointer...
		int[] textures = new int[1];
		gl.glGenTextures(1, textures, 0);
		textureID = textures[0];

		// ...and bind it to our array
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureID);

		// Create Nearest Filtered Texture
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
				GL10.GL_LINEAR);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
				GL10.GL_LINEAR);

		// Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
				GL10.GL_CLAMP_TO_EDGE);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
				GL10.GL_REPEAT);

		// Use the Android GLUtils to specify a two-dimensional texture image
		// from our bitmap
		GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
	}
	
	private void setVerticesBuffer(float[] vertices) {
		
		ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);
		vbb.order(ByteOrder.nativeOrder());
		verticesBuffer = vbb.asFloatBuffer();
		verticesBuffer.put(vertices);
		verticesBuffer.position(0);
	}
	
	private void setIndicesBuffer(short[] indices) {
		
		ByteBuffer ibb = ByteBuffer.allocateDirect(indices.length*2);
		ibb.order(ByteOrder.nativeOrder());
		indicesBuffer = ibb.asShortBuffer();
		indicesBuffer.put(indices);
		indicesBuffer.position(0);
		
		numOfIndices = indices.length;
	}
	
	private void setTextureCoordsBuffer(float[] textureCoords) {
		
		ByteBuffer tbb = ByteBuffer.allocateDirect(textureCoords.length*4);
		tbb.order(ByteOrder.nativeOrder());
		textureCoordsBuffer = tbb.asFloatBuffer();
		textureCoordsBuffer.put(textureCoords);
		textureCoordsBuffer.position(0);
	}

	public boolean isTouched() {
		return touched;
	}

	public void setTouched(boolean touched) {
		this.touched = touched;
	}
	
}
